package link

import (
	"bufio"
	"fmt"
	"math/rand"
	"os"
	"time"

	"github.com/molio/practice/ds/utils"
)

type SingleLinkedList struct {
	Head *Node
}

func NewSingleLinkedList() *SingleLinkedList {
	return &SingleLinkedList{Head: NewNode(0)}
}

func (sll *SingleLinkedList) IsEmpty() bool {
	return sll.Head.Next == nil
}

func (sll *SingleLinkedList) GetLength() int {
	if sll.IsEmpty() {
		return 0
	}
	cNode := sll.Head.Next
	nlen := 0
	for cNode != nil {
		nlen += 1
		cNode = cNode.Next
	}
	return nlen
}

func (sll *SingleLinkedList) CreateSingleLinkedList(isRandom bool, nlen int) {
	cNode := sll.Head
	if isRandom {
		rand.Seed(time.Now().Unix())
		for i := 0; i < nlen; i++ {
			node := NewNode(rand.Intn(100) + 1)
			cNode.Next = node
			cNode = cNode.Next
		}
	} else {
		var num int
		f := bufio.NewReader(os.Stdin)
		for {
			fmt.Println("请输入数字，回车继续，#结束")
			input, _ := f.ReadString('\n')
			if input == "#\n" {
				break
			}
			fmt.Sscan(input, &num)
			node := NewNode(num)
			cNode.Next = node
			cNode = cNode.Next
		}

	}
}

func (sll *SingleLinkedList) TravelSingleLinkedList() {
	cNode := sll.Head
	fmt.Printf("该节点为：head")
	for cNode != nil {
		if cNode.Data != 0 {
			fmt.Printf("->%v", cNode.Data)
		}
		cNode = cNode.Next
	}
	fmt.Println()
}

func (sll *SingleLinkedList) InsertElementInTail() {
	fmt.Println("尾插法")
	num := utils.ReadInput()
	node := NewNode(num)
	cNode := sll.Head
	for cNode.Next != nil {
		cNode = cNode.Next
	}
	cNode.Next = node
}

func (sll *SingleLinkedList) InsertElementInHead() {
	fmt.Println("头插法")
	num := utils.ReadInput()
	node := NewNode(num)
	cNode := sll.Head
	if cNode.Next == nil {
		cNode.Next = node
	} else {
		node.Next = cNode.Next
		cNode.Next = node
	}
}

func (sll *SingleLinkedList) FindElemnent(num int) (*Node, int) {
	if sll.IsEmpty() {
		return nil, 0
	}
	fmt.Println("查找元素")
	if num == 0 {
		num = utils.ReadInput()
	}
	cNode := sll.Head.Next
	pos := 0
	for cNode != nil {
		if cNode.Data == num {
			return cNode, pos
		}
		cNode = cNode.Next
		pos += 1
	}
	return nil, 0
}

func (sll *SingleLinkedList) FindElemnentByPos(pos int) (*Node, int) {
	if sll.IsEmpty() {
		return nil, 0
	}
	fmt.Printf("根据位置: %d 查找元素\n", pos)
	cNode := sll.Head.Next
	ppos := 0
	for cNode != nil {
		if ppos == pos {
			return cNode, pos
		}
		cNode = cNode.Next
		ppos += 1
	}
	return nil, 0
}

func (sll *SingleLinkedList) FindElemnentPreNode(num int) (*Node, int) {
	if sll.IsEmpty() {
		return nil, 0
	}
	fmt.Printf("查找元素: %d 的前置结点\n", num)
	if num == 0 {
		num = utils.ReadInput()
	}
	cNode := sll.Head
	pos := 0
	for cNode.Next != nil {
		if cNode.Next.Data == num {
			return cNode, pos
		}
		cNode = cNode.Next
		pos += 1
	}
	return nil, 0
}

func (sll *SingleLinkedList) DeleteElement(num int) {
	preNode, _ := sll.FindElemnentPreNode(num)
	if preNode == nil {
		fmt.Println("未找到待删除元素")
		return
	}
	node := preNode.Next
	preNode.Next = node.Next
}

// 反转单链表
func RevertSingleLinkedList(list *SingleLinkedList) *SingleLinkedList {
	fmt.Println("反转链表")
	if list.IsEmpty() {
		return nil
	}
	cNode := list.Head.Next
	list.Head.Next = nil
	for cNode != nil {
		tmpNode := cNode.Next
		cNode.Next = list.Head
		list.Head = cNode
		cNode = tmpNode
	}
	return list
}
